home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-09-28 | 10.9 KB | 363 lines | [TEXT/CWIE] |
- /************************************************************************************
- Apple Macintosh Developer Technical Support
-
- Standard File Sample Application
-
- StdFile
-
- StdFile.p - Pascal Source
-
- Copyright © 1989 Apple Computer, Inc.
- All rights reserved.
-
- Versions:
- 1.00 04/89
- 2.00 05/90
- 2.01 06/92
-
- 3/17/98 AB Removed all System 6 compatibility code
- Removed all A/UX compatibility code
-
- Components:
- StdFile.p April 1, 1989
- StdFile.h April 1, 1988
- StdFile.r April 1, 1988
- PStdFile.make April 1, 1988
-
- ----------
- OBJECTIVES
- ----------
- This program attempts to demonstrate the following techniques:
-
- - Normal use of SFGetFile and SFPutFile
- - Normal use of SFPGetFile and SFPPutFile. This includes use of Custom
- Dialogs with handling of extra items through the implementation of a
- Standard File Dialog Hook.
- - First time initialization
- - Extra Simple buttons (Disory/ThisDir/Options)
- - Radio buttons (file format, types of files to show)
- - Aliasing click on some buttons to clicks on other buttons
- - Regenerating the list of files displayed
- - Creating a full pathname from the reply record (using Working Directories
- or DirID)
- - Selecting a directory (ala MPW's "GetFileName -d")
- - Simple file filter (checks file type)
- - Complex file filter (looking inside the file)
- - Adding and deleting and extra List Manager lists. This is shown for both
- SFGetFile and SFPutFile.
- - Select multiple files by adding a second list to the Dialog Box.
- - Setting the starting Directory/Volume
- - Describe pending update event clogging
- - Ask the user to select a file, and then remember where it is the next
- time the application is launched.
-
- --------------------------
- Standard File Generalities
- --------------------------
-
- The prompt string of SFGetFile is ignored in all calls. As noted on page
- I-523 of Inside Mac, it is there for historical reasons only. The
- Standard File package is built around a modal dialog window. Standard
- File repeatedly calls ModalDialog waiting for user events. It is
- possible for an application to hook into the dialog event loop by using
- the following methods.
-
- File Filter
- -----------
- The file filter is called to give the application opportunity to filter
- out files that is wishes not to be shown in the dialog. This file filter
- is called before displaying the dialog, which is also before the Dialog
- Hook or Dialog Filter are called. If this function returns TRUE, this
- means the file should not be shown in the list. In other words the file
- is to be filtered from the user.
-
- Dialog Hook
- -----------
- The dialog hook is called after Standard File calls ModalDialog. The
- hook is a function that requires that an item number be passed back from
- it. Normally, this is the same item number that was passed to us, but
- not necessarily. For instance, we could return values that cause the
- file names to be re-drawn or have the whole event ignored. Before the
- dialog is drawn, our dialog hook gets called with a -1. This gives us
- the opportunity to change things like Button titles, etc. It's in
- important to note that Standard File seems to ignore the item returned by
- the dialog hook when it is called the first time. The dialog hook will
- also be passed a fake item of 100, which is used to mean a nullEvent.
- This can be used as an idle event for the dialog hook.
-
- Dialog Filter
- -------------
- This is used in the SFPGetFile and SFPPutFile routines. It is for the
- advanced versions of calling Standard File for programmers that desire a
- custom dialog window. The dialog filter is the same filter procedure
- used by the Dialog Manager. In the call to ModalDialog, you can supply a
- filter. The dialog filter used by Standard File is passed to
- ModalDialog. This filter is called by the Dialog Manager after it calls
- GetNextEvent. This gives the filter the first opportunity to handle the
- event. If the dialog filter returns TRUE, this tells the Dialog Manager
- that the filter has handled the event. You will use the dialog filter to
- handle items you've added to your custom dialog.
-
- ************************************************************************************/
- /*
- #include <stddef.h>
- #include <types.h>
- #include <limits.h>
- #include <Builtins.h>
- #include <PStrings.h>
- #include <PSets.h>
-
- #include <Types.h>
- #include <QuickDraw.h>
- #include <ToolUtils.h>
- #include <Controls.h>
- #include <Devices.h>
- #include <Traps.h>
- #include <Resources.h>
- #include <Packages.h>
- #include <Lists.h>
- #include <DiskInit.h>
- #include <Script.h>
- #include <LowMem.h>
- #include <CursorCtl.h>
- #include <Errors.h>
- #include <FixMath.h>
- #include <GestaltEqu.h>
- #include <StandardFile.h>
- */
-
-
- // **************** Universal Headers ****************
-
- #include <Dialogs.h>
- #include <Events.h>
- #include <Files.h>
- #include <Fonts.h>
- #include <Memory.h>
- #include <Menus.h>
- #include <SegLoad.h>
- #include <Windows.h>
-
- #include "StdFile.h"
-
-
- // **************** Globals ****************
-
- // gInBackground is maintained by the osEvent handling routines. Any part of
- // the program can check it to find out if it is currently in the background.
-
- Boolean gInBackground; // maintained by Initialize and EventLoop
-
- FSSpec gAppFSSpec; // The FSSpec for the application
- //Str255 gAppName; //application's name
- //long gAppParID; //dirID of application's folder
- //short gAppVRefNum; //volume containing application
-
-
-
-
- // ****************************************************************
-
- void EventLoop( void );
- void Initialize( void );
- void EmergencyExit( short message );
- Boolean FailLowMemory(long memRequest);
-
-
- // ****************************************************************
-
- void main( void )
- {
- //If you have stack requirements that differ from the default, then you
- //could use SetApplLimit to increase StackSpace at this point, before
- //calling MaxApplZone.
-
- MaxApplZone(); //expand the heap so code segments load at the top
- Initialize(); //initialize the program
- UnloadSeg(Initialize); //note: Initialize must not be in Main!
- EventLoop(); //call the main event loop
- }//end main
-
- // ****************************************************************
-
- void Initialize( void )
- {
- /*
- The pentultimate thing is to save the default directory and volume
- that the application is launched from in two globals and create a
- temporary file. This file is only used for demonstration purposes.
- Finally, we check if the file we last remembered can be found.
- */
-
- Str63 fName;
- EventRecord event;
- Handle menuBar;
- Handle apParam;
- OSErr ignoreError;
- short count;
- short auxVersion;
- short appResRef;
- OSErr err;
- Boolean ignoreResult;
- Str63 Temp_Str63_1;
- FSSpec fss;
-
- gInBackground = false; // we’ll be in the foreground soon
-
- for ( count = 0; count < kNumberOfMasters; ++count ) // allocate master pointer blocks
- {
- MoreMasters();
- }
- InitGraf( &qd.thePort );
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( nil );
- InitCursor();
-
- menuBar = GetNewMBar( rMenuBar ); // read menus into menu bar
- if (menuBar == NULL)
- {
- EmergencyExit( sNoMenus );
- }
-
- SetMenuBar( menuBar ); // install menus
- DisposeHandle( menuBar );
- AppendResMenu( GetMenuHandle(mApple), 'DRVR' ); // add DA names to Apple menu
- DrawMenuBar();
-
- if ( FailLowMemory( kMinSpace ) )
- {
- EmergencyExit( sLowMemory );
- }
-
- anErr = GetCurrentProcessFSSpec( &gAppFSSpec );
- if ( anErr == noErr )
- {
- gAppVRefNum = fss.vRefNum;
- gAppParID = fss.parID;
- }
- err = HCreate( gAppVRefNum, gAppParID, GetTempFileName((Str63 *)Temp_Str63_1),
- rAppSignature, 'TEMP');
-
- RecallFile(); //what was that file?
- }//end Initialize
-
- // ****************************************************************
-
- void EventLoop( void )
- {
- //Chances are, you've seen an event loop before so I'm not going to
- //comment about it.
-
- const char osEvt = app4Evt; //defined in post MPW 3.0 Events.p
- const char suspendResumeMessage = 1; //defined in post MPW 3.0 Events.p
- const char kGetHighByte = 24; //24 bits (three bytes) to shift right
- const char kResumeMask = 1; //resume event is low bit of message
-
- EventRecord evt;
- WindowPtr whichWindow; //used for FindWindow
- short deskPart; //result from FindWindow
- OSErr err;
- Boolean haveEvent; //TRUE if interesting event
-
- do {
- if (gHasWaitNextEvent)
- haveEvent = WaitNextEvent(everyEvent, &evt, LONG_MAX, NULL);
- else {
- SystemTask();
- haveEvent = GetNextEvent(everyEvent, &evt);
- }
-
- deskPart = FindWindow(evt.where, &whichWindow);
- if (deskPart != inSysWindow)
- SetCursor(&qd.arrow);
-
- if (haveEvent) {
- switch (evt.what) {
-
- case mouseDown:
- switch (deskPart) {
- case inSysWindow:
- SystemClick(&evt, whichWindow);
- break;
- case inMenuBar:
- DoCommand(MenuSelect(evt.where));
- break;
- }
- break;
-
- case keyDown:
- case autoKey:
- if (BAnd(evt.modifiers, cmdKey) != 0)
- DoCommand(MenuKey((char)BAnd(evt.message, charCodeMask)));
- break;
-
- case diskEvt:
- //Call DIBadMount in response to a diskEvt
- if (HiWord(evt.message) != noErr)
- err = DIBadMount((Point)kSFTopLeft, evt.message);
- break;
-
- case osEvt:
- switch (BSR(evt.message, kGetHighByte)) {
- case suspendResumeMessage:
- if (BAnd(evt.message, kResumeMask) != 0) {
- gInBackground = false;
- } else
- gInBackground = true; //suspend event
- break; //suspendResumeMessage
- }
- break;
- }
-
- //CASE
- }
- } while (true); //loop forever, quit through Terminate
- }
-
- // ****************************************************************
-
- void EmergencyExit( short message )
- {
- //Display an alert that tells the user an error occurred, then exit the
- //program. This routine is used as an ultimate bail-out for serious errors
- //that prohibit the continuation of the application. Errors that do not
- //require the termination of the application are handled with AlertUser.
- //Error checking and reporting has a place even in the simplest application.
-
- //BUG NOTE: GetIndString will return a bogus String if the index is not
- //positive.
-
- Str255 msg1;
- short theItem;
-
- SetCursor(&qd.arrow);
- if (message > 0)
- GetIndString(msg1, rErrStrings, message);
- else
- PStr_Set(msg1, "\p"); //in case there is no message
- ParamText(msg1, "\p", "\p", "\p");
- theItem = CenteredAlert(rExitAlert);
- ExitToShell(); //we're out of here
- }
-
- // ****************************************************************
-
- Boolean FailLowMemory(long memRequest)
- {
- //Call PurgeSpace and see if the requested amount of memory exists in the
- //heap including a minimal amount of heap space. Also, if my grow zone’s
- //reserve has been release, that’s considered a failure. I don’t perform
- //any purging here. The Memory Manager will do this if it needs the space.
- //This routine can be called with a memRequest = 0. This checks if the heap
- //space is getting critical.
-
- long total;
- long contig;
-
- PurgeSpace(&total, &contig);
- return total < memRequest + kMinSpace;
- }
-